package hos.thread.hander;


import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import hos.thread.RunnableThis;
import hos.thread.ThreadOption;

/**
 * <p>Title: MainHandler </p>
 * <p>Description: 主线程切换 </p>
 * <p>Company: www.mapuni.com </p>
 *
 * @author : 蔡俊峰
 * @version : 1.0
 * @date : 2023/8/9 17:30
 */
public class MainHandler extends Handler {

    protected MainHandler() {
        //默认是主线程
        super(Looper.getMainLooper());
    }

    private static volatile MainHandler handler;

    public static MainHandler handler() {
        if (handler == null) {
            synchronized (MainHandler.class) {
                if (handler == null) {
                    handler = get();
                }
            }
        }
        return handler;
    }

    private static MainHandler get() {
        return new MainHandler();
    }

    public static MainHandler run(Runnable runnable) {
        return run(ThreadOption.UI.ON, 300, runnable);
    }

    public static MainHandler run(ThreadOption.UI handle, Runnable runnable) {
        return run(handle, 300, runnable);
    }

    public static MainHandler run(ThreadOption.UI handle, long time, Runnable runnable) {
        return handler().start(handle, time, runnable);
    }

    public static boolean isMainThread() {
        return Looper.getMainLooper().getThread() == Thread.currentThread();
    }

    /**
     * 切换到主线程
     *
     * @param runnable 主线程
     */
    public MainHandler postToMain(Runnable runnable) {
        post((RunnableThis) run -> {
            try {
                runnable.run();
            } finally {
                removeCallbacks(run);
                Log.d("Thread", "main removeCallbacks");
            }
        });
        return this;
    }

    /**
     * 在主线程上运行
     *
     * @param runnable 主线程
     */
    public MainHandler postOnMain(Runnable runnable) {
        if (isMainThread()) {
            runnable.run();
        } else {
            postToMain(runnable);
        }
        return this;
    }

    public MainHandler start(Runnable runnable) {
        return start(ThreadOption.UI.ON, 300, runnable);
    }

    public MainHandler start(ThreadOption.UI handle, Runnable runnable) {
        return start(handle, 300, runnable);
    }

    public MainHandler start(ThreadOption.UI handle, long time, Runnable runnable) {
        if (handle == ThreadOption.UI.TO) {
            return postToMain(runnable);
        }
        if (handle == ThreadOption.UI.DELAYED) {
            postDelayed((RunnableThis) run -> {
                try {
                    runnable.run();
                } finally {
                    removeCallbacks(run);
                    Log.d("Thread", "main removeCallbacks");
                }
            }, time);
            return this;
        }
        if (handle == ThreadOption.UI.TIME) {
            postAtTime((RunnableThis) run -> {
                try {
                    runnable.run();
                } finally {
                    removeCallbacks(run);
                    Log.d("Thread", "main removeCallbacks");
                }
            }, time);
            return this;
        }
        return postOnMain(runnable);
    }


    @Override
    public void dispatchMessage(Message msg) {
        if (msg == null) {
            Log.d("Thread", "msg is null , return");
            return;
        }
        try {
            super.dispatchMessage(msg);
        } catch (Exception e) {
            Log.d("Thread", "dispatchMessage Exception " + msg + " , " + e);
        } catch (Error error) {
            Log.d("Thread", "dispatchMessage error " + msg + " , " + error);
        }
    }

    public void remove(Runnable runnable) {
        removeCallbacks(runnable);
    }

    public void clearCallback() {
        removeCallbacksAndMessages(null);
    }

}
